import { useLoader } from "@react-three/fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { Canvas, useFrame, useThree, extend } from "@react-three/fiber";
import { useEffect, useRef, useState, Suspense, startTransition } from "react";
import { useTranslation } from "react-i18next";
import { Button, Select } from "antd";
import outfitAThumb from "./assets/thumbs/outfitA.png";
import outfitBThumb from "./assets/thumbs/outfitB.png";
import outfitCThumb from "./assets/thumbs/outfitC.png";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { AnimationMixer, LoopOnce, LoopRepeat, Box3, Vector3 } from "three";
import * as THREE from "three";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
import { useNavigate } from "react-router-dom";

extend({ OrbitControls });

const Orbit = ({ controlsRef }: { controlsRef: any }) => {
    const { camera, gl } = useThree();
    return <orbitControls ref={controlsRef} args={[camera, gl.domElement]} />;
};


interface MySelfProps {
  currentAction?: string
  onActionChange?: (action: string) => void
}

function MySelf({ currentAction, onActionChange }: MySelfProps) {
    const navigate = useNavigate();
    const { t } = useTranslation();
    const mySelfRef = useRef<any>(null);
    const [modelUrl, setModelUrl] = useState<string>("/avatar.glb");
    const model = useLoader(GLTFLoader, modelUrl);
    const controlsRef = useRef<any>(null);
    const mixerRef = useRef<AnimationMixer | null>(null);
    const actionsRef = useRef<Record<string, any>>({});
    const DEFAULT_ACTION = "zhanli"; // 默认站立
    const [active, setActive] = useState<string>(DEFAULT_ACTION);
    // 动作状态管理
    // 位置锁定
    const modelPositionRef = useRef<{ x: number; y: number; z: number } | null>(null);
    const modelScaleRef = useRef<{ x: number; y: number; z: number } | null>(null);

    // ========== Mouth (WebAudio) ==========
    const audioElRef = useRef<HTMLAudioElement | null>(null);
    const audioCtxRef = useRef<AudioContext | null>(null);
    const analyserRef = useRef<AnalyserNode | null>(null);
    const dataArrayRef = useRef<Uint8Array | null>(null);
    const volumeSmoothRef = useRef<number>(0);
    const mediaSourceRef = useRef<MediaElementAudioSourceNode | null>(null);
    const mediaElementRef = useRef<HTMLMediaElement | null>(null);
    const micStreamRef = useRef<MediaStream | null>(null);
    const audioObjectUrlRef = useRef<string | null>(null);
    const jawBoneRef = useRef<THREE.Object3D | null>(null);
    const jawBaseRotXRef = useRef<number>(0);
    // 口型形态学备用（当没有下巴骨骼时使用）
    const morphTargetsRef = useRef<Array<{ mesh: any; index: number }>>([]);
    const ctxGenRef = useRef<number>(0);
    
    // ========== 眨眼控制 ==========
    const blinkTimerRef = useRef<number | null>(null);
    
    // 简单眨眼函数 - 只控制眼部，不影响嘴部
    const doBlink = () => {
        try {
            model.scene.traverse((obj: THREE.Object3D) => {
                const name = (obj.name || '').toLowerCase();
                
                // 只控制眼部相关的骨骼，排除嘴部
                if ((name.includes('eyelid') || name.includes('lid') || name.includes('eye')) &&
                    !name.includes('mouth') && !name.includes('lip') && !name.includes('jaw') &&
                    !name.includes('tongue') && !name.includes('teeth')) {
                    
                    
                    // 方法1: 尝试缩放眼皮
                    obj.scale.y = 0.1; // 压缩眼皮
                    setTimeout(() => {
                        obj.scale.y = 1; // 恢复眼皮
                    }, 150);
                    
                    // 方法2: 尝试移动眼皮
                    obj.position.y -= 0.05;
                    setTimeout(() => {
                        obj.position.y += 0.05;
                    }, 150);
                }
                
                // 只控制眼部相关的MorphTargets，排除嘴部
                const mesh = obj as any;
                if (mesh && mesh.morphTargetDictionary && mesh.morphTargetInfluences) {
                    const dict: Record<string, number> = mesh.morphTargetDictionary;
                    
                    for (const key of Object.keys(dict)) {
                        const low = key.toLowerCase();
                        // 只控制眼部相关的变形，明确排除嘴部
                        if ((low.includes('eye') || low.includes('blink') || low.includes('lid') || 
                             low.includes('squint') || low.includes('wink')) && 
                            !low.includes('mouth') && !low.includes('lip') && !low.includes('jaw') && 
                            !low.includes('tongue') && !low.includes('teeth')) {
                            try {
                                mesh.morphTargetInfluences[dict[key]] = 1;
                                setTimeout(() => {
                                    mesh.morphTargetInfluences[dict[key]] = 0;
                                }, 150);
                            } catch {}
                        }
                    }
                }
            });
        } catch (e) {
            console.warn('眨眼失败:', e);
        }
    };

    // 统一的连接函数：确保不会在同一 AudioContext 上为同一元素重复 createMediaElementSource
    const connectElementToAnalyser = async (el: HTMLMediaElement) => {
        const Ctx: any = (window as any).AudioContext || (window as any).webkitAudioContext;
        let ctx = audioCtxRef.current;
        // 如果当前 AudioContext 已经绑定了别的元素，或我们丢失了 source 引用，则重建上下文
        const needRecreateCtx = !ctx || (mediaElementRef.current && mediaElementRef.current !== el) || (mediaElementRef.current === el && !mediaSourceRef.current);
        if (needRecreateCtx) {
            try { await ctx?.close(); } catch {}
            ctx = new Ctx();
            audioCtxRef.current = ctx;
            mediaSourceRef.current = null;
            mediaElementRef.current = null;
            // 严格重置与旧上下文有关的节点
            try { analyserRef.current?.disconnect(); } catch {}
            analyserRef.current = null;
            dataArrayRef.current = null;
            ctxGenRef.current += 1;
        }
        if (ctx!.state === 'suspended') await ctx!.resume();

        if (!mediaSourceRef.current) {
            const source = ctx!.createMediaElementSource(el);
            mediaSourceRef.current = source;
            mediaElementRef.current = el;
        }
        // 确保分析器属于当前上下文
        let analyser = analyserRef.current;
        // @ts-ignore
        const analyserCtx = (analyser as any)?.context as AudioContext | undefined;
        if (!analyser || analyserCtx !== ctx) {
            try { analyser?.disconnect(); } catch {}
            analyser = ctx!.createAnalyser();
        }
        analyser.fftSize = 1024;
        analyser.smoothingTimeConstant = 0.6;
        const dataArray = new Uint8Array(analyser.fftSize);
        // 重新连接链路，避免多次 connect 叠加
        try { mediaSourceRef.current.disconnect(); } catch {}
        mediaSourceRef.current.connect(analyser);
        analyser.connect(ctx!.destination);
        analyserRef.current = analyser;
        dataArrayRef.current = dataArray;
        volumeSmoothRef.current = 0;
    };

    // 确保跨域音频可供 WebAudio 使用 + 监听播放状态
    useEffect(() => {
        const el = audioElRef.current as any;
        if (el) {
            try { el.crossOrigin = 'anonymous'; } catch {}
            // 音频播放事件处理
            const noop = () => {};
            el.addEventListener('play', noop);
            el.addEventListener('pause', noop);
            el.addEventListener('ended', noop);
            return () => {
                el.removeEventListener('play', noop);
                el.removeEventListener('pause', noop);
                el.removeEventListener('ended', noop);
            };
        }
    }, []);

    useEffect(() => {
        if (!model?.scene) return;
        
        // 将模型在 X 轴上居中到世界原点
        try {
            const box = new Box3().setFromObject(model.scene);
            const center = new Vector3();
            box.getCenter(center);
            model.scene.position.x -= center.x;
            
            // 记录初始位置和缩放，用于锁定
            // 注意：这里记录的是模型本身的position，Canvas中的primitive position={[0, -1.5, 0]}是额外的
            modelPositionRef.current = {
                x: model.scene.position.x,
                y: model.scene.position.y,
                z: model.scene.position.z
            };
            modelScaleRef.current = {
                x: model.scene.scale.x,
                y: model.scene.scale.y,
                z: model.scene.scale.z
            };
        } catch {}

        // 修复某些角度头部被半透明衣物遮挡的问题：
        // - 半透明材质不写入深度，避免把后方头部遮掉
        // - 头/脸相关网格强制不透明并提高渲染顺序
        try {
            model.scene.traverse((obj: THREE.Object3D) => {
                const mesh = obj as THREE.Mesh;
                if (!(mesh as any).isMesh) return;
                // 对所有蒙皮网格关闭视锥裁剪，避免动画导致包围盒错误
                if ((mesh as any).isSkinnedMesh) {
                    mesh.frustumCulled = false;
                }
                const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];

                materials.forEach((mat: any) => {
                    if (!mat) return;
                    // 若存在透明贴图或不完全不透明，则优先使用 alphaTest 走不透明管线
                    const hasAlpha = !!mat.alphaMap || (typeof mat.opacity === 'number' && mat.opacity < 1);
                    if (hasAlpha) {
                        mat.transparent = false;
                        mat.alphaTest = Math.max(0.4, mat.alphaTest || 0.5);
                        mat.depthTest = true;
                        mat.depthWrite = true;
                    } else if (mat.transparent === true) {
                        // 保持半透明但避免遮挡：不写深度
                        mat.depthTest = true;
                        mat.depthWrite = false;
                    }

                    // 识别头/脸相关网格或材质名
                    const nameJoined = `${mesh.name || ''}|${mat.name || ''}`.toLowerCase();
                    const looksLikeHead = /(head|face|hair|skin|头|脸)/.test(nameJoined);
                    const looksLikeCloth = /(shirt|tee|tshirt|hood|hoodie|jacket|coat|cloth|sweater|upper|torso|衣|上衣|外套|卫衣)/.test(nameJoined);
                    if (looksLikeHead) {
                        // 头部使用不透明渲染，且优先绘制
                        mat.transparent = false;
                        mat.depthWrite = true;
                        mesh.renderOrder = 10;
                        // 为安全起见，允许双面，避免法线方向问题
                        if (typeof mat.side !== 'undefined') mat.side = THREE.DoubleSide;
                        mesh.frustumCulled = false;
                    } else if (looksLikeCloth) {
                        // 上衣：避免背面消失与遮挡
                        if (typeof mat.side !== 'undefined') mat.side = THREE.DoubleSide;
                        mat.depthTest = true;
                        mat.depthWrite = true;
                        // 若有透明贴图，采用 alphaTest 走不透明管线
                        const hasAlpha = !!mat.alphaMap || (typeof mat.opacity === 'number' && mat.opacity < 1);
                        if (hasAlpha) {
                            mat.transparent = false;
                            mat.alphaTest = Math.max(0.4, mat.alphaTest || 0.5);
                        }
                        mesh.renderOrder = 5;
                    }
                });
            });
        } catch {}

        // 记录下巴骨骼以便驱动嘴型（若存在）
        try {
            let found: THREE.Object3D | null = null;
            const candidates: Array<{ mesh: any; index: number }> = [];
            const targetNameList = ['mouthopen', 'jawopen', 'viseme_aa', 'viseme_o', 'viseme_ih', 'viseme_e'];
            model.scene.traverse((obj: THREE.Object3D) => {
                const name = (obj.name || '').toLowerCase();
                if (!found && (name.includes('jaw') || name.includes('下巴') || name.includes('mouth'))) {
                    found = obj;
                }
                const mesh = obj as any;
                if (mesh && mesh.morphTargetDictionary && mesh.morphTargetInfluences) {
                    const dict: Record<string, number> = mesh.morphTargetDictionary;
                    // 优先 mouthOpen / jawOpen / viseme_aa
                    for (const key of Object.keys(dict)) {
                        const low = key.toLowerCase();
                        if (targetNameList.some(t => low.includes(t))) {
                            candidates.push({ mesh, index: dict[key] });
                        }
                    }
                }
            });
            morphTargetsRef.current = candidates;
            if (found) {
                jawBoneRef.current = found;
                jawBaseRotXRef.current = (found as any).rotation?.x || 0;
            } else {
                jawBoneRef.current = null;
            }
        } catch {}

        // 将轨道控制的目标指向原点，保证围绕中心旋转
        if (controlsRef.current && controlsRef.current.target) {
            controlsRef.current.target.set(0, 0, 0);
        }
        
        // 初始化眨眼状态，确保眼睛是睁开的
        setTimeout(() => {
        }, 100);
        
        // 启动每4秒眨眼定时器
        blinkTimerRef.current = window.setInterval(() => {
            doBlink();
        }, 4000);

        const loader = new FBXLoader();
        const load = (url: string) => new Promise<any>((resolve, reject) => 
            loader.load(url, resolve, undefined, reject)
        );

        const init = async () => {
            try {
                const [dance, flair, guixia, daiji, zhanli, zhanli2, smoking] = await Promise.all([
                    load("/animations/silly_dancing.fbx"),
                    load("/animations/Flair.fbx"),
                    load("/animations/guixia.fbx"),
                    load("/animations/daiji.fbx"),
                    load("/animations/zhanli.fbx"),
                    load("/animations/zhanli2.fbx"),
                    load("/animations/Smoking.fbx").catch(() => null),
                ]);

                const mixer = new AnimationMixer(model.scene);
                mixerRef.current = mixer;

                const danceClip = dance?.animations?.[0];
                const flairClip = flair?.animations?.[0];
                const guixiaClip = guixia?.animations?.[0];
                const daijiClip = daiji?.animations?.[0];
                const zhanliClip = zhanli?.animations?.[0];
                const zhanli2Clip = zhanli2?.animations?.[0];
                const smokingClip = smoking?.animations?.[0];
                
                if (danceClip) actionsRef.current["dance"] = mixer.clipAction(danceClip);
                if (flairClip) actionsRef.current["flair"] = mixer.clipAction(flairClip);
                if (guixiaClip) actionsRef.current["guixia"] = mixer.clipAction(guixiaClip);
                if (daijiClip) actionsRef.current["daiji"] = mixer.clipAction(daijiClip);
                if (zhanliClip) actionsRef.current["zhanli"] = mixer.clipAction(zhanliClip);
                if (zhanli2Clip) actionsRef.current["zhanli2"] = mixer.clipAction(zhanli2Clip);
                if (smokingClip) actionsRef.current["smoking"] = mixer.clipAction(smokingClip);

                // 默认播放站立（循环）
                const defaultAction = actionsRef.current[DEFAULT_ACTION];
                if (defaultAction) {
                    defaultAction.reset();
                    defaultAction.setLoop(LoopRepeat, Infinity);
                    defaultAction.fadeIn(0.3).play();
                    setActive(DEFAULT_ACTION);
                } else {
                    // 兜底：选择任一可用动作
                    const any = Object.values(actionsRef.current)[0];
                    if (any) {
                        any.reset();
                        any.setLoop(LoopOnce, 1);
                        any.fadeIn(0.3).play();
                    }
                }
            } catch (e) {
                console.warn("Failed to load animations:", e);
            }
        };
        
        init();

        return () => {
            if (mixerRef.current) {
                mixerRef.current.stopAllAction();
                mixerRef.current = null;
            }
            // 清理音频
            try {
                const el = audioElRef.current;
                if (el) {
                    el.pause();
                    el.src = '';
                }
            } catch {}
            if (mediaSourceRef.current) {
                try { mediaSourceRef.current.disconnect(); } catch {}
                mediaSourceRef.current = null;
            }
            mediaElementRef.current = null;
            if (audioObjectUrlRef.current) {
                URL.revokeObjectURL(audioObjectUrlRef.current);
                audioObjectUrlRef.current = null;
            }
            if (micStreamRef.current) {
                micStreamRef.current.getTracks().forEach(t => t.stop());
                micStreamRef.current = null;
            }
            if (audioCtxRef.current) {
                audioCtxRef.current.close();
                audioCtxRef.current = null;
            }
            analyserRef.current = null;
            dataArrayRef.current = null;
            volumeSmoothRef.current = 0;
            
            // 清理眨眼定时器
            if (blinkTimerRef.current) {
                clearInterval(blinkTimerRef.current);
                blinkTimerRef.current = null;
            }
        };
    }, [model]);

    // 监听外部动作变化（来自语音指令）
    useEffect(() => {
        if (currentAction && currentAction !== active) {
            console.log('🎭 外部动作变化:', currentAction)
            playAction(currentAction)
        }
    }, [currentAction])

    const playAction = (name: string) => {
        const actions = actionsRef.current;
        const next = actions[name];
        
        // 动作播放逻辑
        
        if (!next) return;
        
        Object.values(actions).forEach((act: any) => {
            if (act === next) return;
            act.fadeOut(0.3);
        });
        
        next.reset();
        
        // 设置播放次数
        if (name === DEFAULT_ACTION) {
            // 默认动作（站立）无限循环
            next.setLoop(LoopRepeat, Infinity);
        } else if (name === 'dance' || name === 'flair') {
            // 跳舞和街舞播放3次
            next.setLoop(LoopRepeat, 3);
        } else if (name === 'smoking') {
            // 吸烟动作播放1次
            next.setLoop(LoopRepeat, 1);
        } else {
            // 其他动作（待机、站立2、跪下）单次播放
            next.setLoop(LoopOnce, 1);
        }
        
        // 当非默认动作结束后，自动回到默认动作
        next.clampWhenFinished = true;
        next.fadeIn(0.3).play();
        if (name !== DEFAULT_ACTION) {
            next.getMixer().addEventListener('finished', function handler(e: any) {
                // 只响应当前动作结束
                if (e.action !== next) return;
                next.getMixer().removeEventListener('finished', handler);
                const def = actionsRef.current[DEFAULT_ACTION];
                if (def) {
                    Object.values(actionsRef.current).forEach((act: any) => act !== def && act.fadeOut(0.2));
                    def.reset();
                    def.setLoop(LoopRepeat, Infinity);
                    def.fadeIn(0.2).play();
                    setActive(DEFAULT_ACTION);
                }
            });
        }
        setActive(name);
    };

    // 切换整套服装（替换模型文件）
    const switchOutfit = (url: string) => {
        if (!url || url === modelUrl) return;
        // 重置为默认动作名，模型加载完成后会按默认动作播放
        setActive(DEFAULT_ACTION);
        // 模型加载会触发 Suspense，使用 startTransition 避免同步输入时报错
        startTransition(() => setModelUrl(url));
    };

    const MixerUpdater = ({ mixer }: { mixer: React.MutableRefObject<AnimationMixer | null> }) => {
        useFrame((_state, delta) => {
            if (mixer.current) mixer.current.update(delta);
            
            // 位置锁定代码已移除（说话动作已删除）
            
            // 音量 -> 嘴型（下巴旋转 或 形态学）
            const analyser = analyserRef.current;
            const data = dataArrayRef.current;
            const jaw = jawBoneRef.current;
            if (analyser && data) {
                analyser.getByteTimeDomainData(data);
                // 计算 RMS
                let sum = 0;
                for (let i = 0; i < data.length; i++) {
                    const v = (data[i] - 128) / 128;
                    sum += v * v;
                }
                const rms = Math.sqrt(sum / data.length);
                // 平滑
                const prev = volumeSmoothRef.current || 0;
                const smooth = prev * 0.85 + rms * 0.15;
                volumeSmoothRef.current = smooth;
                // 映射到嘴巴开合 [0, 1]
                const mouth = Math.min(1, Math.max(0, (smooth - 0.008) * 14));
                if (jaw) {
                    const baseX = jawBaseRotXRef.current || 0;
                    jaw.rotation.x = baseX + mouth * 0.4; // ~23°
                } else if (morphTargetsRef.current.length) {
                    for (const item of morphTargetsRef.current) {
                        try {
                            if (item.mesh.morphTargetInfluences && item.mesh.morphTargetInfluences[item.index] != null) {
                                item.mesh.morphTargetInfluences[item.index] = mouth;
                            }
                        } catch {}
                    }
                }
                ;(window as any).__mouth = { rms: Number(rms.toFixed(4)), mouth: Number(mouth.toFixed(3)), hasJaw: !!jaw, morphTargets: morphTargetsRef.current.length };
            }
        });
        return null;
    };

    // 嘴部驱动相关功能

    // ========== TTS 驱动入口 ==========
    const startAudioMouthFromBlob = async (file: Blob) => {
        try {
            // 断开旧资源
            if (micStreamRef.current) {
                micStreamRef.current.getTracks().forEach(t => t.stop());
                micStreamRef.current = null;
            }
            if (audioObjectUrlRef.current) {
                URL.revokeObjectURL(audioObjectUrlRef.current);
                audioObjectUrlRef.current = null;
            }
            const url = URL.createObjectURL(file);
            audioObjectUrlRef.current = url;
            const el = audioElRef.current;
            if (!el) return;
            el.src = url;
            el.currentTime = 0;

            // 确保 AudioContext 就绪
            await connectElementToAnalyser(el);

            try { await el.play(); } catch (e) { console.warn('Audio play blocked:', e); }
        } catch (e) {
            console.error(e);
        }
    };

    const driveMouthFromBlob = async (blob: Blob) => {
        await startAudioMouthFromBlob(blob);
    };

    const driveMouthFromUrl = async (url: string) => {
        try {
            const res = await fetch(url);
            const ct = res.headers.get('content-type') || '';
            if (ct.includes('audio')) {
                const blob = await res.blob();
                await driveMouthFromBlob(blob);
            } else {
                // 回退：直接播放 URL（若跨域允许）
                const el = audioElRef.current;
                if (!el) return;
                el.src = url;

                await connectElementToAnalyser(el);

                try { await el.play(); } catch (e) { console.warn('Audio play blocked:', e); }
            }
        } catch (e) {
            console.error(e);
        }
    };

    // 暴露为全局函数
    (window as any).driveMouthFromBlob = driveMouthFromBlob;
    (window as any).driveMouthFromUrl = driveMouthFromUrl;
    (window as any).testBlink = doBlink; // 测试眨眼

    // 将外部已有 <audio>/<video> 元素接入分析器
    const attachMouthToAudioElement = async (el: HTMLMediaElement) => {
        if (!el) return;
        try {
            await connectElementToAnalyser(el);
        } catch (e) {
            console.error('attachMouthToAudioElement failed:', e);
        }
    };

    const autoAttachMouth = async () => {
        const candidates = Array.from(document.querySelectorAll('audio,video')) as HTMLMediaElement[];
        for (const el of candidates) {
            if (!el) continue;
            try {
                if (!el.paused && !el.muted && el.volume > 0) {
                    await attachMouthToAudioElement(el);
                    return true as any;
                }
            } catch {}
        }
        // 没找到就监听下一次播放事件
        const once = async (ev: Event) => {
            const target = ev.target as HTMLMediaElement;
            document.removeEventListener('play', once, true);
            await attachMouthToAudioElement(target);
        };
        document.addEventListener('play', once, true);
        return false as any;
    };

    (window as any).attachMouthToAudioElement = attachMouthToAudioElement;
    (window as any).autoAttachMouth = autoAttachMouth;

    // 组件渲染

    return (
        <div style={{ height: "100%", width: "100%", position: "relative" }}>
            <audio ref={audioElRef} style={{ display: 'none' }} />
            <Canvas camera={{ position: [1, 0.25, 2.5] }}>
                <Suspense fallback={null}>
                    <Orbit controlsRef={controlsRef} />
                    <MixerUpdater mixer={mixerRef} />
                    <mesh ref={mySelfRef}>
                        <hemisphereLight intensity={0.15} groundColor="black" />
                        <ambientLight />
                        <directionalLight position={[10, 10, 5]} intensity={1} />
                        <primitive object={model.scene} scale={1.3} position={[0, -1.5, 0]} rotation={[0, Math.PI / 6, 0]} />
                    </mesh>
                </Suspense>
            </Canvas>
            {/* 左上方框区域：移动下拉框 */}
            <div style={{ position: "absolute", top: 130, left: 22, zIndex: 10000, pointerEvents: 'auto' }}>
                <Select
                    value={active}
                    style={{ width: 160, zIndex: 10001 }}
                    onChange={(val) => playAction(val)}
                    options={[
                        { label: t('actions.standing'), value: "zhanli" },
                        { label: t('actions.standby'), value: "daiji" },
                        { label: t('actions.standing2'), value: "zhanli2" },
                        { label: t('actions.dance'), value: "dance" },
                        { label: t('actions.streetDance'), value: "flair" },
                        { label: t('actions.kneel'), value: "guixia" },
                        { label: "吸烟动作", value: "smoking" },
                    ]}
                />
            </div>

            <div style={{ position: "absolute", top: 120, right: 100, zIndex: 10000, pointerEvents: 'auto' }}>
                <Button 
                    onClick={() => {
                        // 提取当前角色的名称
                        const characterName = modelUrl.replace('.glb', '').replace('/', '');
                        // 跳转到展览馆并传递角色参数
                        navigate(`/guan?character=${characterName}`);
                    }}
                    style={{ zIndex: 10001, pointerEvents: 'auto' }}
                >
                    {t('menu.home')}
                </Button>
            </div>

            {/* 左侧圆形按钮占位：用于换装 */}
            <div style={{ position: "absolute", top: 250, left: 18, display: "flex", flexDirection: "column", gap: 34, zIndex: 10000, pointerEvents: 'auto' }}>
                {[
                    { key: 'A', url: '/avatar.glb', thumb: outfitAThumb },
                    { key: 'B', url: '/avatar2.glb', thumb: outfitBThumb },
                    { key: 'C', url: '/avatar3.glb', thumb: outfitCThumb },
                ].map((item) => (
                    <button
                        key={item.key}
                        aria-label={`switch-outfit-${item.key}`}
                        style={{
                            width: 65,
                            height: 65,
                            borderRadius: '50%',
                            border: '2px solid rgba(255,255,255,0.6)',
                            background: item.thumb
                                ? `url('${item.thumb}') center/cover no-repeat`
                                : 'rgba(0,0,0,0.25)',
                            overflow: 'hidden',
                            boxShadow: '0 2px 8px rgba(0,0,0,0.25)',
                            cursor: 'pointer',
                            zIndex: 10001,
                            pointerEvents: 'auto'
                        }}
                        onClick={() => switchOutfit(item.url)}
                    />
                ))}
            </div>

            {/* 组件内容 */}
        </div>
    );
}

export default MySelf;